C++ Basics

Throwing Exceptions

It is possible for you to throw an exception of your own choosing. All you need is the keyword throw. You can create an instance of any class you want, and it can be either a pointer or a direct instance.

# include <iostream> // std::cout, std::endl

double divide(double a, double b)
{
    if(b == 0)
        throw std::string("Can't divide by 0");
    return (a / b);
}

int main()
{
    double x = 21;
    double y = 0;
    try
    {
        std::cout << "Result of division is: " << divide(x, y) << std::endl;
    }
    catch(std::string& exp)
    {
        std::cout << "Exception: " << exp << std::endl;
    }
    return 0;
}

A throw consists of the keyword throw followed by an expression. The type of the expression determines what kind of exception is thrown.

Besides throwing direct instances, we can also throw instances created with the new operator:

throw new string("Oops, I found some bad data!");

Because in the function we threw a pointer to a string instance, we catch a pointer to a string instance. Everything must match.

catch(string *excep)

When inside a catch block, a throw statement without anything after it will re-throw the same exception. Although this may seem a bit convoluted (and indeed it can be), you may have a function that contains a try / catch block. But this function might also be called by another function that has a try / catch block. In other words, you might have something like this:

# include <iostream>     // std::cout, std::endl
# include <string>       // std::string

void inner()
{
    throw std::string("Error!");
}
void outer()
{
    try
    {
        inner();
    }
    catch(std::string excep)
    {
        std::cerr << "outer caught an exception: "
              << excep << std::endl;
        throw;
    }
}

int main()
{
    try
    {
        outer();
    }
    catch(std::string excep)
    {
        std::cerr << "main caught an exception: "
              << excep << std::endl;
    }
    return 0;
}

Console output:

outer caught an exception: Error!
main caught an exception: Error!

Older code may contain dynamic exception specifications. They are now deprecated in C++, but still supported. A dynamic exception specification follows the declaration of a function, appending a throw specifier to it. For example:

double myfunction (char param) throw (int);

This declares a function called myfunction(char), which takes one argument of type char and returns a value of type double. If this function throws an exception of some type other than int, the function calls std::unexpected instead of looking for a handler or calling std::terminate.

If this throw specifier is left empty with no type, this means that std::unexpected is called for any exception. Functions with no throw specifier (regular functions) never call std::unexpected, but follow the normal path of looking for their exception handler.

int myfunction (int param) throw(); // all exceptions call unexpected
int myfunction (int param);         // normal exception handling